/*
 * @Author: shawnxiao
 * @Date: 2021-05-17 16:46:55
 * @LastEditTime: 2021-11-17 18:48:52
 * @FilePath: /gatt-react/src/components/DynamicFormReader/FormFieldRender.tsx
 */
/* eslint-disable react/display-name */

import React, {Fragment} from 'react'
import { Form, Input, InputNumber, Cascader, DatePicker, TimePicker, Checkbox, Radio, TreeSelect, Row, Col, Slider, Switch, Button } from 'antd'
const { Search, TextArea, Password } = Input
const FormItem = Form.Item
import { uuid } from '@/common/utils'
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'

import { FormFieldSelect, SketchPickerField } from './FormField'

const FormFields = {
  select: (config:any, formRef:any) => {
    return <FormFieldSelect config={config} formRef={formRef}/>
  },
  // select: (config:any) => {
  //   const {placeholder, list = [], onChange = () => {}, ...rest} = config
  //   return h(
  //     Select, {placeholder, labelInValue: true, onChange: v => onChange(v), ...rest},
  //     list.map((c:any) => h(Option, {key: c.value, value: c.value} as any, c.label))
  //   )
  // },
  input: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, tooltip, rules, fieldKey, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <Input {...rest} />
      </FormItem>
    )
  },
  inputNumber: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, tooltip, fieldKey, rules, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <InputNumber {...rest} />
      </FormItem>
    )
  },
  search: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, tooltip, fieldKey, rules, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <Search {...rest} />
      </FormItem>
    )
  },
  textArea: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, tooltip, fieldKey, rules, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <TextArea {...rest} />
      </FormItem>
    )
  },
  password: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, tooltip, fieldKey, rules, ...rest} = config
    return (
    <FormItem
      className="form-item-com-custom"
      initialValue={value}
      data-index={dataIndex}
      label={title}
      tooltip={tooltip}
      name={key}
      fieldKey={fieldKey}
      key={`${key}-${uuid(5)}`}
      rules={rules}
      labelCol={labelCol}
      wrapperCol={wrapperCol}>
      <Password {...rest} />
    </FormItem>
    )
  },
  slider: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, tooltip, fieldKey, rules, ...rest} = config
    return (
    <FormItem
      className="form-item-com-custom"
      initialValue={value}
      data-index={dataIndex}
      label={title}
      tooltip={tooltip}
      name={key}
      fieldKey={fieldKey}
      key={`${key}-${uuid(5)}`}
      rules={rules}
      labelCol={labelCol}
      wrapperCol={wrapperCol}>
      <Slider {...rest}/>
    </FormItem>
    )
  },
  switch: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, valuePropName = 'checked', dataIndex, tooltip, fieldKey, rules, ...rest} = config
    return (
    <FormItem
      className="form-item-com-custom"
      initialValue={value}
      valuePropName={valuePropName}
      data-index={dataIndex}
      label={title}
      tooltip={tooltip}
      name={key}
      fieldKey={fieldKey}
      key={`${key}-${uuid(5)}`}
      rules={rules}
      labelCol={labelCol}
      wrapperCol={wrapperCol}>
      <Switch {...rest}/>
    </FormItem>
    )
  },
  sketchPicker: (config:any, formRef:any) => <SketchPickerField config={config} formRef={formRef}/>,
  datePicker: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, tooltip, fieldKey, rules, format, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <DatePicker {...rest} format={format || 'YYYY-MM-DD'} />
    </FormItem>
    )
  },
  dateRangePicker: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, fieldKey, tooltip, rules, format, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <DatePicker.RangePicker format={format || 'YYYY-MM-DD'} {...rest}/>
      </FormItem>
    )
  },
  timePicker: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, fieldKey, tooltip, rules, format, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <TimePicker {...rest} format={format || 'HH:mm:ss'} />
      </FormItem>
    )
  },
  timeRangePicker: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, fieldKey, tooltip, rules, format, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <TimePicker.RangePicker {...rest} format={format || 'HH:mm:ss'} />
      </FormItem>
    )
  },
  cascader: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, tooltip, fieldKey, rules, dataIndex, expandTrigger = 'hover', fieldNames = '{label: "label",value: "value",children: "children"}', ...rest} = config
    return (
      <FormItem
      className="form-item-com-custom"
      initialValue={value}
      data-index={dataIndex}
      label={title}
      tooltip={tooltip}
      name={key}
      fieldKey={fieldKey}
      key={`${key}-${uuid(5)}`}
      rules={rules}
      labelCol={labelCol}
      wrapperCol={wrapperCol}>
      <Cascader expandTrigger={expandTrigger} fieldNames={fieldNames} {...rest} />
    </FormItem>
    )
    // return h(
    //   FormItem, {initialValue: value, key, label: title, labelCol, wrapperCol, tooltip, rules},
    //   h(Cascader, {expandTrigger, fieldNames, onChange: (v, ...p) => onChange(v, ...p), ...rest})
    // )
  },
  checkbox: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, valuePropName = 'checked', dataIndex, fieldKey, tooltip, rules, checked, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        valuePropName={valuePropName}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <Checkbox checked={checked} {...rest}>{title}</Checkbox>
      </FormItem>
    )
  },
  checkboxGroup: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, valuePropName = 'checked', dataIndex, fieldKey, tooltip, rules, options, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        valuePropName={valuePropName}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <Checkbox.Group options={options} {...rest}/>
      </FormItem>
    )
  },
  radio: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, valuePropName = 'checked', dataIndex, fieldKey, tooltip, rules, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        valuePropName={valuePropName}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <Radio {...rest}>{title}</Radio>
      </FormItem>
    )
  },
  radioGroup: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, valuePropName = 'checked', dataIndex, fieldKey, tooltip, rules, options, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        valuePropName={valuePropName}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <Radio.Group options={options} {...rest}></Radio.Group>
      </FormItem>
    )
  },
  treeSelect: (config:any) => {
    const {value, key, title, labelCol = {span: 10, offset: 0}, wrapperCol = {span: 24, offset: 0}, dataIndex, fieldKey, tooltip, rules, treeData, ...rest} = config
    return (
      <FormItem
        className="form-item-com-custom"
        initialValue={value}
        data-index={dataIndex}
        label={title}
        tooltip={tooltip}
        name={key}
        fieldKey={fieldKey}
        key={`${key}-${uuid(5)}`}
        rules={rules}
        labelCol={labelCol}
        wrapperCol={wrapperCol}>
        <TreeSelect treeData={treeData} {...rest}/>
      </FormItem>
    )
  }
}

// 字段列表类型渲染
function FieldListRender (props:any) {
  const {field, columns, formRef} = props
  return (
    <Fragment>
      {
        columns.map((config:any) => {
          const { type = 'input', key, colSpan = 12, ...rest} = config, FormField = FormFields[type]
          const params = {
            key: field && Object.keys(field)?.length ? [field.name, key] : key,
            // formList动态表单的时候需要fieldKey
            fieldKey: field && Object.keys(field)?.length ? [field.name, key] : null,
            ...rest
          }
          return (
            <Fragment key={key}>
              {
                FormField ? (
                  <Col key={key} span={colSpan}>
                    {FormField(params, formRef)}
                  </Col>
                ) : type === 'formList' ? <FormListRender config={config} formRef={formRef}/> : null
              }
            </Fragment>
          )
        })
      }
    </Fragment>
  )
}
// 动态表单
function FormListRender(props:any) {
  const {config, formRef} = props
  const { list, title, key} = config
  return (
    <Form.List name={key}>
      {(fields, { add, remove }, { errors }) => {
        return (
          <>
            {fields.map((field) => (
              <Fragment key={field.key}>
                <Form.Item noStyle>
                  {/* Form.List动态表单需要传field */}
                  <FieldListRender field={field} columns={list} formRef={formRef}/>
                  {fields.length >= 1 ? (
                    <Col span={2}>
                      <MinusCircleOutlined
                        className="dynamic-delete-button"
                        style={{marginTop: '40px'}}
                        onClick={() => remove(field.name)}
                      />
                    </Col>
                  ) : null}
                </Form.Item>
              </Fragment>
            ))}
            <Col span={24}>
              <Form.Item>
                <Button
                  type="dashed"
                  onClick={() => add()}
                  style={{ width: '60%' }}
                  icon={<PlusOutlined />}
                >
                  {title || 'Add field'}
                </Button>
                <Form.ErrorList errors={errors} />
              </Form.Item>
            </Col>
          </>
        )
      }}
    </Form.List>
  )
}

function FormFieldRender(props: any) {
  const {columns, gutter, formRef} = props
  return (
    <Row gutter={gutter}>
    <FieldListRender columns={columns} formRef={formRef}/>
  </Row>
  )
}

export default FormFieldRender
